home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / event-tty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-04  |  7.9 KB  |  310 lines

  1. /* The event_stream interface for tty's.
  2.    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
  3.  
  4. This file is part of XEmacs.
  5.  
  6. XEmacs is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by the
  8. Free Software Foundation; either version 2, or (at your option) any
  9. later version.
  10.  
  11. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with XEmacs; see the file COPYING.  If not, write to the Free
  18. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Synched up with: Not in FSF. */
  21.  
  22. #include <config.h>
  23. #include "lisp.h"
  24.  
  25. #include "blocktype.h"
  26. #include "device.h"
  27. #include "device-tty.h"
  28. #include "events.h"
  29. #include "frame.h"
  30. #include "process.h"
  31.  
  32. #include "sysproc.h"
  33. #include "syswait.h"
  34. #include "systime.h"
  35.  
  36. /* Mask of bits indicating the descriptors that we wait for input on */
  37. extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
  38. extern SELECT_TYPE process_only_mask, device_only_mask;
  39.  
  40. extern Lisp_Object Qdelete_device;
  41.  
  42. static struct event_stream *tty_event_stream;
  43.  
  44.  
  45. /************************************************************************/
  46. /*                timeout events                */
  47. /************************************************************************/
  48.  
  49. /* The pending timers are stored in an ordered list, where the first timer
  50.    on the list is the first one to fire.  Times recorded here are
  51.    absolute. */
  52. static struct low_level_timeout *tty_timer_queue;
  53.  
  54. static int
  55. emacs_tty_add_timeout (EMACS_TIME time)
  56. {
  57.   return add_low_level_timeout (&tty_timer_queue, time);
  58. }
  59.  
  60. static void
  61. emacs_tty_remove_timeout (int id)
  62. {
  63.   remove_low_level_timeout (&tty_timer_queue, id);
  64. }
  65.  
  66. static void
  67. tty_timeout_to_emacs_event (struct Lisp_Event *emacs_event)
  68. {
  69.   emacs_event->event_type = timeout_event;
  70.   emacs_event->timestamp  = 0; /* #### */
  71.   emacs_event->event.timeout.interval_id =
  72.     pop_low_level_timeout (&tty_timer_queue, 0);
  73. }
  74.  
  75.  
  76.  
  77. static int
  78. emacs_tty_event_pending_p (int user_p)
  79. {
  80.   if (!user_p)
  81.     {
  82.       EMACS_TIME sometime;
  83.       /* see if there's a pending timeout. */
  84.       EMACS_GET_TIME (sometime);
  85.       if (tty_timer_queue &&
  86.       EMACS_TIME_EQUAL_OR_GREATER (sometime, tty_timer_queue->time))
  87.     return 1;
  88.     }
  89.  
  90.   return poll_fds_for_input (user_p ? device_only_mask :
  91.                  non_fake_input_wait_mask);
  92. }
  93.  
  94. static struct device *
  95. find_device_from_fd (int fd)
  96. {
  97.   Lisp_Object rest;
  98.  
  99.   DEVICE_LOOP (rest)
  100.     {
  101.       struct device *d;
  102.  
  103.       assert (DEVICEP (XCAR (rest)));
  104.       d = XDEVICE (XCAR (rest));
  105.       if (DEVICE_IS_TTY (d) && fileno (DEVICE_TTY_DATA (d)->infd) == fd)
  106.     return d;
  107.     }
  108.  
  109.   return 0;
  110. }
  111.  
  112. int
  113. read_event_from_tty_or_stream_desc (struct Lisp_Event *event,
  114.                     struct device *d, int fd)
  115. {
  116.   unsigned char ch;
  117.   int nread;
  118.  
  119.   nread = read (fd, &ch, 1);
  120.   if (nread == 0)
  121.     {
  122.       Lisp_Object device;
  123.       XSETDEVICE (device, d);
  124.       /* deleting the device might not be safe right now ... */
  125.       Fenqueue_eval_event (Qdelete_device, device);
  126.       /* but we definitely need to unselect it to avoid infinite
  127.      loops reading EOF's */
  128.       Fdevice_disable_input (device);
  129.     }
  130.   else if (nread > 0)
  131.     {
  132.       character_to_event (ch, event, d);
  133.       event->channel = DEVICE_SELECTED_FRAME (d);
  134.       return 1;
  135.     }
  136.   else
  137.     {
  138.       /* #### What to do if there's an error? */
  139.     }
  140.   return 0;
  141. }
  142.  
  143. int
  144. maybe_read_quit_event (struct Lisp_Event *event)
  145. {
  146.   /* A C-g that came from `sigint_happened' will always come from the
  147.      controlling terminal.  If that doesn't exist, however, then the
  148.      user manually sent us a SIGINT, and we pretend the C-g came from
  149.      the selected-device. */
  150.   struct device *d;
  151.  
  152.   if (DEVICEP (Vcontrolling_terminal) &&
  153.       DEVICE_LIVE_P (XDEVICE (Vcontrolling_terminal)))
  154.     d = XDEVICE (Vcontrolling_terminal);
  155.   else
  156.     d = XDEVICE (Fselected_device ());
  157.  
  158.   if (sigint_happened)
  159.     {
  160.       int ch = DEVICE_QUIT_CHAR (d);
  161.       sigint_happened = 0;
  162.       Vquit_flag = Qnil;
  163.       character_to_event (ch, event, d);
  164.       event->channel = DEVICE_SELECTED_FRAME (d);
  165.       return 1;
  166.     }
  167.   return 0;
  168. }
  169.  
  170. static void
  171. emacs_tty_next_event (struct Lisp_Event *emacs_event)
  172. {
  173.   while (1)
  174.     {
  175.       int ndesc;
  176.       int i;
  177.       SELECT_TYPE temp_mask = input_wait_mask;
  178.       EMACS_TIME time_to_block;
  179.       EMACS_SELECT_TIME select_time_to_block, *pointer_to_this;
  180.  
  181.       if (!get_low_level_timeout_interval (tty_timer_queue, &time_to_block))
  182.     /* no timer events; block indefinitely */
  183.      pointer_to_this = 0;
  184.       else
  185.     {
  186.       EMACS_TIME_TO_SELECT_TIME (time_to_block, select_time_to_block);
  187.       pointer_to_this = &select_time_to_block;
  188.     }
  189.  
  190.       ndesc = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
  191.       if (ndesc > 0)
  192.     {
  193.       /* Look for a TTY event */
  194.       for (i = 0; i < MAXDESC; i++)
  195.         {
  196.           /* To avoid race conditions (among other things, an infinite
  197.          loop when called from Fdiscard_input()), we must return
  198.          user events ahead of process events. */
  199.           if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &device_only_mask))
  200.         {
  201.           struct device *d = find_device_from_fd (i);
  202.           
  203.           assert (d);
  204.           if (read_event_from_tty_or_stream_desc (emacs_event, d, i))
  205.             return;
  206.         }
  207.         }
  208.  
  209.       /* Look for a process event */
  210.       for (i = 0; i < MAXDESC; i++)
  211.         {
  212.           if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &process_only_mask))
  213.         {
  214.           Lisp_Object process;
  215.           struct Lisp_Process *p =
  216.             get_process_from_input_descriptor (i);
  217.           
  218.           assert (p);
  219.           XSETPROCESS (process, p);
  220.           emacs_event->event_type = process_event;
  221.           emacs_event->timestamp  = 0; /* #### */
  222.           emacs_event->event.process.process = process;
  223.           return;
  224.         }
  225.         }
  226.  
  227.       /* We might get here when a fake event came through a signal. */
  228.       /* Return a dummy event, so that a cycle of the command loop will
  229.          occur. */
  230.       drain_signal_event_pipe ();
  231.       emacs_event->event_type = eval_event;
  232.       emacs_event->event.eval.function = Qidentity;
  233.       emacs_event->event.eval.object = Qnil;
  234.       return;
  235.     }
  236.       else if (ndesc == 0) /* timeout fired */
  237.     {
  238.       tty_timeout_to_emacs_event (emacs_event);
  239.       return;
  240.     }
  241.     }
  242. }
  243.  
  244. static void
  245. emacs_tty_handle_magic_event (struct Lisp_Event *emacs_event)
  246. {
  247.   /* Nothing to do currently */
  248. }
  249.  
  250.  
  251. static void
  252. emacs_tty_select_process (struct Lisp_Process *process)
  253. {
  254.   /* Nothing to do currently */
  255. }
  256.  
  257. static void
  258. emacs_tty_unselect_process (struct Lisp_Process *process)
  259. {
  260.   /* Nothing to do currently */
  261. }
  262.  
  263. static void
  264. emacs_tty_select_device (struct device *d)
  265. {
  266.   /* Nothing to do currently */
  267. }
  268.  
  269. static void
  270. emacs_tty_unselect_device (struct device *d)
  271. {
  272.   /* Nothing to do currently */
  273. }
  274.  
  275. static void
  276. emacs_tty_quit_p (void)
  277. {
  278.   /* Nothing to do currently because QUIT is handled through SIGINT.
  279.      This could change. */
  280. }
  281.  
  282.  
  283. /************************************************************************/
  284. /*                            initialization                            */
  285. /************************************************************************/
  286.  
  287. void
  288. vars_of_event_tty (void)
  289. {
  290.   tty_event_stream =
  291.     (struct event_stream *) xmalloc (sizeof (struct event_stream));
  292.  
  293.   tty_event_stream->event_pending_p     = emacs_tty_event_pending_p;
  294.   tty_event_stream->next_event_cb    = emacs_tty_next_event;
  295.   tty_event_stream->handle_magic_event_cb = emacs_tty_handle_magic_event;
  296.   tty_event_stream->add_timeout_cb     = emacs_tty_add_timeout;
  297.   tty_event_stream->remove_timeout_cb     = emacs_tty_remove_timeout;
  298.   tty_event_stream->select_device_cb     = emacs_tty_select_device;
  299.   tty_event_stream->unselect_device_cb     = emacs_tty_unselect_device;
  300.   tty_event_stream->select_process_cb     = emacs_tty_select_process;
  301.   tty_event_stream->unselect_process_cb = emacs_tty_unselect_process;
  302.   tty_event_stream->quit_p_cb        = emacs_tty_quit_p;
  303. }
  304.  
  305. void
  306. init_event_tty_late (void)
  307. {
  308.   event_stream = tty_event_stream;
  309. }
  310.